package com.torfox.modules.logview;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import lombok.Setter;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.MutablePeriod;
import org.joda.time.format.PeriodFormatterBuilder;
import org.joda.time.format.PeriodParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJacksonJsonView;

import com.torfox.entities.LogRecord;
import com.torfox.services.ILoggingService;

@Controller
@SessionAttributes("model")
public class LogViewController
{
	@Autowired
	@Setter
	private ILoggingService loggingService;

	@RequestMapping(value = "/logs.do", method = RequestMethod.GET)
	public ModelAndView main()
	{
		final List<String> levels = loggingService.getLevels();
		final List<String> senders = loggingService.getSenders();
		final LogViewModel model = new LogViewModel();
		model.setLimit(100);
		model.setPage(1);
		final ModelAndView mav = new ModelAndView("main", "model", model);
		final List<LogRecord> records = loggingService.getLogs(model.getLimit());
		mav.addObject("model", model);
		mav.addObject("records", records);
		mav.addObject("levels", levels);
		mav.addObject("senders", senders);
		return mav;
	}

	@RequestMapping(value = "/logs.do", method = RequestMethod.POST)
	public ModelAndView filter(@ModelAttribute("model") final LogViewModel model)
	{
		Date end = null;
		Date start = null;
		final PeriodParser parser = new PeriodFormatterBuilder()
		        .appendHours().
		        appendSeparator(":").
		        appendMinutes().
		        appendSeparator(":").
		        appendSeconds().toParser();
		if (model.getDate() != null)
		{
			final DateTime dateTime = new DateTime(model.getDate());
			if (!StringUtils.isBlank(model.getTimeStart()))
			{
				final MutablePeriod period = new MutablePeriod();
				parser.parseInto(period, model.getTimeStart(), 0, Locale.getDefault());
				start = dateTime.plus(period).toDate();
			}
			else
			{
				start = dateTime.toLocalDate().toDateTimeAtStartOfDay().toDate();
			}
			if (!StringUtils.isBlank(model.getTimeEnd()))
			{
				final MutablePeriod period = new MutablePeriod();
				parser.parseInto(period, model.getTimeEnd(), 0, Locale.getDefault());
				end = dateTime.plus(period).toDate();
			}
			else
			{
				end = dateTime.toLocalDate().toDateTimeAtStartOfDay().plusDays(1).minusMillis(1).toDate();
			}
		}
		final List<LogRecord> records = loggingService.getLogs(
		        model.getLimit(), start, end, model.getSender(),
		        model.getFilterLevel(), model.getFilterPattern(),
		        model.getFilterClass(), model.getFilterExceptionClass());
		final List<String> levels = loggingService.getLevels();
		final List<String> senders = loggingService.getSenders();
		final ModelAndView mav = new ModelAndView("main", "model", model);
		mav.addObject("model", model);
		mav.addObject("records", records);
		mav.addObject("levels", levels);
		mav.addObject("senders", senders);
		return mav;
	}

	@RequestMapping("/record.do")
	public ModelAndView singleRecord(@RequestParam("id") final Long recordId)
	{
		final LogRecord logRecord = loggingService.getLogRecord(recordId);
		final MappingJacksonJsonView view = new MappingJacksonJsonView();
		view.setBeanName("record");
		final ModelAndView mav = new ModelAndView(view);
		mav.addObject("record", logRecord);
		return mav;
	}

	@RequestMapping("/exceptions.do")
	public ModelAndView findExceptionClasses(@RequestParam("term") final String term)
	{
		final List<String> exceptions = loggingService.getExceptions(term);
		final MappingJacksonJsonView view = new MappingJacksonJsonView();
		view.setBeanName("record");
		final ModelAndView mav = new ModelAndView(view);
		mav.addObject("exceptions", exceptions);
		return mav;
	}

	@InitBinder
	public void initBinder(final WebDataBinder binder) throws Exception
	{
		final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		final CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
		binder.registerCustomEditor(Date.class, editor);
	}
}